package com.xuelang.pipeline.infrastructure.pipeline.repository;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuelang.pipeline.client.common.result.PageRecord;
import com.xuelang.pipeline.client.pipeline.dto.TagQuery;
import com.xuelang.pipeline.domain.pipeline.Tag;
import com.xuelang.pipeline.domain.pipeline.repository.TagRepository;
import com.xuelang.pipeline.infrastructure.pipeline.converter.TagToTagDOConverter;
import com.xuelang.pipeline.infrastructure.pipeline.dataobject.TagDO;
import com.xuelang.pipeline.infrastructure.pipeline.mapper.TagMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 流水线标签仓库实现类
 *
 * @author xiwen.zxg
 * @since 2024/5/15
 */
@Slf4j
@Repository
public class TagRepositoryImpl implements TagRepository {

    @Autowired
    TagMapper tagMapper;

    @Override
    public PageRecord<Tag> pageList(long currentPage, long pageSize, TagQuery tagQuery) {
        currentPage = currentPage < 1 ? 1 : currentPage;
        pageSize = pageSize < 1 ? 10 : pageSize;
        Page<TagDO> page = new Page<>(currentPage, pageSize);
        LambdaQueryWrapper<TagDO> wrapper = Wrappers.lambdaQuery(TagDO.class);
        if (tagQuery != null) {
            if (StringUtils.isNotBlank(tagQuery.getUuid())) {
                wrapper.eq(TagDO::getUuid, tagQuery.getUuid());
            }
            if (StringUtils.isNotBlank(tagQuery.getName())) {
                wrapper.like(TagDO::getName, tagQuery.getName());
            }
            if (StringUtils.isNotBlank(tagQuery.getType())) {
                wrapper.eq(TagDO::getType, tagQuery.getType());
            }
            if (StringUtils.isNotBlank(tagQuery.getColor())) {
                wrapper.eq(TagDO::getColor, tagQuery.getColor());
            }
        }
        tagMapper.selectPage(page, wrapper);
        return new PageRecord<>(
                page.getCurrent(),
                page.getSize(),
                page.getTotal(),
                page.getPages(),
                page.getRecords().stream().map(TagToTagDOConverter.INSTANCE::tagDOToTag).collect(Collectors.toList())
        );
    }

    @Override
    public List<Tag> list(TagQuery tagQuery) {
        LambdaQueryWrapper<TagDO> wrapper = Wrappers.lambdaQuery(TagDO.class);
        if (tagQuery != null) {
            if (StringUtils.isNotBlank(tagQuery.getUuid())) {
                wrapper.eq(TagDO::getUuid, tagQuery.getUuid());
            }
            if (StringUtils.isNotBlank(tagQuery.getName())) {
                wrapper.like(TagDO::getName, tagQuery.getName());
            }
            if (StringUtils.isNotBlank(tagQuery.getType())) {
                wrapper.eq(TagDO::getType, tagQuery.getType());
            }
            if (StringUtils.isNotBlank(tagQuery.getColor())) {
                wrapper.eq(TagDO::getColor, tagQuery.getColor());
            }
        }
        return tagMapper.selectList(wrapper).stream()
                .map(TagToTagDOConverter.INSTANCE::tagDOToTag).collect(Collectors.toList());
    }


    @Override
    public Boolean save(Tag tag) {
        return tagMapper.insert(TagToTagDOConverter.INSTANCE.tagToTagDO(tag)) == 1;
    }

    @Override
    public Boolean update(Tag tag) {
        return tagMapper.update(
                TagToTagDOConverter.INSTANCE.tagToTagDO(tag),
                Wrappers.lambdaQuery(TagDO.class).eq(TagDO::getUuid, tag.getUuid())) == 1;
    }

    @Override
    public Boolean batchSaveOrUpdate(List<Tag> tagList, String creatorId, Date createTime) {
        List<TagDO> doList = tagList.stream()
                .map(TagToTagDOConverter.INSTANCE::tagToTagDO)
                .collect(Collectors.toList());

        // 分离新增加的标签和已有的标签
        List<TagDO> newTags = Lists.newArrayList();
        List<TagDO> existingTags = Lists.newArrayList();

        for (TagDO tagDO : doList) {
            if (StringUtils.isBlank(tagDO.getUuid())) {
                // 新增加的标签
                tagDO.setUuid(IdUtil.fastSimpleUUID());
                tagDO.setCreatorId(creatorId);
                tagDO.setCreateTime(createTime);
                newTags.add(tagDO);
            } else {
                // 已有的标签
                tagDO.setUpdaterId(creatorId);
                tagDO.setUpdateTime(createTime);
                existingTags.add(tagDO);
            }
        }

        // 获取当前所有标签的UUID
        List<String> currentUuids = tagMapper.selectAllUuids();
        List<String> incomingUuids = doList.stream()
                .map(TagDO::getUuid)
                .collect(Collectors.toList());

        // 找出需要删除的旧标签UUID
        List<String> uuidsToDelete = currentUuids.stream()
                .filter(uuid -> !incomingUuids.contains(uuid))
                .collect(Collectors.toList());

        // 批量删除旧标签
        if (!uuidsToDelete.isEmpty()) {
            tagMapper.deleteByUuids(uuidsToDelete);
        }

        // 批量插入新增加的标签
        if (!newTags.isEmpty()) {
            tagMapper.insertBatch(newTags, creatorId, createTime);
        }

        // 批量更新已有的标签
        if (!existingTags.isEmpty()) {
            tagMapper.updateBatch(existingTags, creatorId, createTime);
        }

        return true;
    }

    @Override
    public Boolean delete(String uuid) {
        return tagMapper.delete(Wrappers.lambdaQuery(TagDO.class).eq(TagDO::getUuid, uuid)) == 1;
    }

    @Override
    public Tag query(String uuid) {
        TagDO tagDO = tagMapper.selectOne(Wrappers.lambdaQuery(TagDO.class).eq(TagDO::getUuid, uuid));
        return TagToTagDOConverter.INSTANCE.tagDOToTag(tagDO);
    }

    @Override
    public List<Tag> queryByUuidList(List<String> uuidList) {
        if (CollectionUtils.isEmpty(uuidList)) {
            return null;
        }
        LambdaQueryWrapper<TagDO> wrapper = Wrappers.lambdaQuery(TagDO.class);
        wrapper.in(TagDO::getUuid, uuidList);
        List<TagDO> wrapperResult = tagMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(wrapperResult)) {
            return null;
        }

        return wrapperResult.stream().map(TagToTagDOConverter.INSTANCE::tagDOToTag).collect(Collectors.toList());
    }

    @Override
    public Boolean existsName(String uuid, String name) {
        List<TagDO> tagList =  tagMapper.selectList(Wrappers.lambdaQuery(TagDO.class).eq(TagDO::getName, name));
        if (ObjectUtil.isEmpty(tagList)) {
            return false;
        }
        return tagList.stream().anyMatch(tagDO -> !StringUtils.equals(uuid, tagDO.getUuid()));
    }

    @Override
    public List<Tag> listByUuidList(List<String> uuidList) {
        return tagMapper.selectList(Wrappers.lambdaQuery(TagDO.class).in(TagDO::getUuid, uuidList))
                .stream().map(TagToTagDOConverter.INSTANCE::tagDOToTag).collect(Collectors.toList());
    }
}
